class RotateBounce3 extends egret.DisplayObjectContainer {
    private ball: Ball
    private lines: Array<Line>
    private numLines: number = 5

    private gravity: number = 0.3
    private bounce: number = -0.6
    private touchX: number = 0
    private touchY: number = 0

    public constructor() {
        super()
        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this)
    }

    private onAddToStage(event: egret.Event) {
        this.ball = new Ball(20)
        this.ball.x = 100
        this.ball.y = 70
        this.addChild(this.ball)

        this.lines = new Array<Line>()
        for (let i = 0; i < this.numLines; ++i) {
            let line = new Line(-50, 0, 50, 0)
            this.addChild(line)
            this.lines.push(line)
        }
        
        this.lines[0].x = 100
        this.lines[0].y = 70
        this.lines[0].rotation = 30

        this.lines[1].x = 100
        this.lines[1].y = 170
        this.lines[1].rotation = 45

        this.lines[2].x = 220
        this.lines[2].y = 120
        this.lines[2].rotation = -30

        this.lines[3].x = 150
        this.lines[3].y = 300
        this.lines[3].rotation = 10

        this.lines[4].x = 230
        this.lines[4].y = 220
        this.lines[4].rotation = -30

        this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.trackTouch, this)
        this.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.trackTouch, this)
        this.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.trackTouch, this)
        this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this)
    }

    private onEnterFrame(event: Event) {
        // 标准的运动代码
        this.ball.vy += this.gravity
        this.ball.x += this.ball.vx
        this.ball.y += this.ball.vy

        // 回弹天花板、地板和墙
        this.checkWall()

        // 检查每个线条
        for (let line of this.lines) {
            this.checkLine(line)
        }
    }

    private checkLine(line: Line) {
        if (this.hitTest(this.ball, line)) {
            // 获得角、正弦和余弦。
            let angle: number = line.rotation * Math.PI / 180
            let cos: number = Math.cos(angle)
            let sin: number = Math.sin(angle)

            // 获得小球相对于线条的位置。
            let x1: number = this.ball.x - line.x
            let y1: number = this.ball.y - line.y

            // 旋转坐标。
            let x2: number = cos * x1 + sin * y1
            let y2: number = cos * y1 - sin * x1

            // 旋转速度。
            let vx1: number = cos * this.ball.vx + sin * this.ball.vy
            let vy1: number = cos * this.ball.vy - sin * this.ball.vx

            // 使用旋转后的值执行回弹
            if (y2 > -this.ball.height / 2 && vy1 > y2) {
                y2 = -this.ball.height / 2
                vy1 *= this.bounce

                // 将所有东西旋转回去
                x1 = cos * x2 - sin * y2
                y1 = cos * y2 + sin * x2
                this.ball.vx = cos * vx1 - sin * vy1
                this.ball.vy = cos * vy1 + sin * vx1
                this.ball.x = line.x + x1
                this.ball.y = line.y + y1
            }
        }
    }

    private checkWall() {
        if (this.ball.x + this.ball.radius > this.stage.stageWidth) {
            this.ball.x = this.stage.stageWidth - this.ball.radius
            this.ball.vx *= this.bounce
        }
        else if (this.ball.x - this.ball.radius < 0) {
            this.ball.x = this.ball.radius
            this.ball.vx *= this.bounce
        }
        if (this.ball.y + this.ball.radius > this.stage.stageHeight) {
            this.ball.y = this.stage.stageHeight - this.ball.radius
            this.ball.vy *= this.bounce
        }
        else if (this.ball.y - this.ball.radius < 0) {
            this.ball.y = this.ball.radius
            this.ball.vy *= this.bounce
        }
    }

    private rotate(cos: number, sin: number, ball: Ball) {
        let x1: number = ball.x - this.stage.stageWidth / 2
        let y1: number = ball.y - this.stage.stageHeight / 2
        let x2: number = cos * x1 - sin * y1
        let y2: number = cos * y1 + sin * x1
        ball.x = this.stage.stageWidth / 2 + x2
        ball.y = this.stage.stageHeight / 2 + y2
    }

    private hitTest(ball: egret.DisplayObject, line: egret.DisplayObject): boolean {
        var bounds: egret.Rectangle = line.getTransformedBounds(this)
        if (ball.x > bounds.left && ball.x < bounds.right) {
            return true
        }

        return false
    }

    private trackTouch(evt: egret.TouchEvent) {
        this.touchX = evt.stageX
        this.touchY = evt.stageY
    }
}